DPDK之ring库源码分析

您所在的位置:网站首页 prod grabby什么意思 DPDK之ring库源码分析

DPDK之ring库源码分析

#DPDK之ring库源码分析| 来源: 网络整理| 查看: 265

前言

此文主要是针对dpdk19.11.5版本进行分析,ring库实现了无锁并发访问,主要用于dpdk多线程间的通信等,所谓的无锁其实是利用了CAS技术,详情看下面的代码分析;

1. Ring结构

ring结构是指环形缓冲区,由一串连续地址空间组成,结构如下图所示:

主要是由rte_ring结构和多个void型指针组成,void型指针最终会指向真实的存储数据的内存地址;

Ring结构有三个主要的操作,创建、入队、出队,下面主要从这个三个操作来分析ring的源码库;

2. Ring结构创建

Ring结构的创建是由rte_ring_create函数完成的,首先计算ring结构所需要的内存空间大小,如下:

其中count最终会要求为2的幂,rte_ring_get_memsize函数最终计算出ring的大小:

和ring结构图一致,由rte_ring结构和多个void型指针组成的大小;

然后申请对应大小的内存块:

最后对ring结构进行初始化:

最主要的是对ring的名字、flag、生产者和消费者头尾指针(下标)、ring大小等变量进行初始化:

到此一个ring结构创建完成,dpdk会对ring结构进行统一管理,用一个全部变量rte_ring_tailq进行管理,把新创建的ring结构入队到rte_ring_tailq的全局队列里:

3. 入队

入队函数有很多,主要是针对消费者、生产者的多个组合来应用的,不过最终都会调用__rte_ring_do_enqueue函数,下面主要分析此函数;

__rte_ring_do_enqueue函数主要分为三个部分:移动生产者头指针、数据入队、更新(移动)生产者尾指针;

在分析源码之前先用图展示一下入队操作,这样比较容易理解源码:

1. 刚开始生产者的头尾指针重合,都指向下一个待入队的空闲位置

2. 如果是多个生产者则竞争头指针,获取到头指针使用权限的生产者根据要入队的个数移动头指针,然后开始入队,这样下一个竞争到头指针使用权的生产者将从移动后的头指针指向的位置开始入队,入队之前同样移动头指针,然后开始入队,这样虽然多个生产者之间竞争头指针是串行的(原子操作),但是入队的过程就形成了并行操作

第一个生产者准备入队1个元素,移动head

第二个生产者准备入队3个元素,移动head

3. 这样在两个生产者入队完成后都开始更新尾指针,当然这个同样是串行的(原子操作),而且是按照先入队先更新顺序

第一个生产者完成入队,开始更新tail

 第二个生产者完成入队,开始更新tail

说明:在此过程中如果第二个生产者先完成了入队,则只能等待第一个生产者更新完成tail后,第二个生产者才能更新tail,这个地方降低了并发的性能,目前分析的是19.11.5版本,在dpdk后面的版本会对此进行优化,不必再按照这个顺序更新tail导致无效的等待;如果是单生产者则无需对head和tail进行竞争,逻辑比较简单,也可以根据上述的图理解入队流程;

以上图示基本是按照入队的三个流程来分析的,首先是竞争头指针使用权,移动头指针:

根据以上图示,最主要的就是竞争头指针使用权,这里用CAS技术进行原子操作来竞争:

然后竞争成功者开始入队操作,逻辑比较简单,就是把ring里的void指针挨个指向存储单元的地址:

最后按照顺序开始更新tail:

以上即为入队操作的整个流程,可以看出,对于多生产者情况,实现了无锁(CAS技术)、并发入队,提高了生产者的效率;

入队完成后,结构如下:

4. 出队

出队操作最终都要调用__rte_ring_do_dequeue函数,如下:

可以看出出队函数同样分为三部分:移动消费者头指针、出队、更新(移动)消费者尾指针,基本和入队流程一样,这里不再详细分析;

总结

理解ring结构的无锁并发实现原理主要是理解两个指针的操作,即位置抢占,通过抢占位置(位置的抢占利用CAS技术保证互斥性,并且速度非常快),给自己预定了要写入数据的位置(空间),然后各自往抢占的位置里写数据,实现了无锁并发访问(相当于抢占位置是有锁的,写数据时是无锁的,把锁用在刀刃上,保证了速度);



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3